/*
 * @Author: qinuoyun
 * @Date:   2019-11-28 12:41:25
 * @Last Modified by:   sean
 * @Last Modified time: 2019-12-25 10:48:31
 */
import Vue from 'vue';

import basics from './basics';

import vmdrag from './drag';

import add_column from './add_column';

import add_label from './add_label';

import add_mark from './add_mark';

import add_edit from './add_edit';

import widgets_column from '../widgets/tables/column';

import widgets_label from '../widgets/forms/label';

/**
 * 拖拽指令类
 */
class dragdrop {
    constructor() {


        /**
         * 工具
         * @type {[type]}
         */
        this.widget = null;
        /**
         * 画布-根节点
         */
        this.canva = null;
        /**
         * 父级
         */
        this.parent = null;
        /**
         * 子集
         */
        this.subset = null;
        /**
         *  结构层
         */
        this.DOM = {};
        /**
         * 数据层
         */
        this.BOM = {};
        /**
         * 数据池
         * @type {Object}
         */
        this.pool = {
            id: 0,
            model: {}
        };
        /**
         * 遮罩存储
         * @type {Array}
         */
        this.mark = []
    }


    /**
     * 操作元素. (component, props, data = {}, el = null, parent = null) {
     * @return {[type]} [description]
     */
    handleEvent(canva, widget, slot) {
        console.log("操作元素-canva", canva);
        console.log("操作元素-widget", widget);
        console.log("操作元素-slot", slot);
        //1.下节点写入数据
        if (slot) {

            widget.location = canva.location + "-" + slot;
            canva.slot[slot] = widget;
        } else {
            let index = canva.slot.length;
            widget.location = canva.location + "-" + index;
            canva.slot.push(widget);
        }
    }

    /**
     * 设置跟节点
     */
    setRoot(component, object) {
        this.canva = {
            id: 'VM_' + component._uid,
            el: component.$el,
            component: component,
            config: object
        }
    }

    /**
     * 初次写入
     * @param {[type]} component [description]
     * @param {String} type      [description]
     */
    setSelf(vnode, type = "install") {
        console.log('setself', vnode);
        /**
         * 初始化设置
         * @type {[type]}
         */
        this.sefl = null;
        let dragdrop = new basics(vnode);
        let id = dragdrop.getID();
        /**
         * 判断跟节点是否存在
         * @return {[type]} [description]
         */
        if (this.canva == null) {
            this.canva = dragdrop;
        }
        /**
         * 操作类型
         * @param  {[type]} type [description]
         * @return {[type]}      [description]
         */
        switch (type) {
            case 'install':
                if (!this.BOM[id]) {
                    this.BOM[id] = dragdrop;
                }
                break;
            case 'update':
                if (vnode.context._uid == Core.canva.uid) {
                    this.canva = dragdrop;
                }
                this.BOM[id] = dragdrop;
                break;
        }
        /**
         * 赋值给当前
         * @type {[type]}
         */
        this.sefl = this.BOM[id];
        return this.sefl;
    }

    getSelf(id) {
        return this.BOM[id];
    }

    /**
     * 设置数据存储
     * @param {[type]} data [description]
     */
    setWidget(data) {
        let value = data.default ? data.default : data;
        this.widget = this.deepCopy(value);
    }

    /**
     * 设置数据存储
     */
    getWidget() {
        return this.widget
    }

    /**
     * 清除存储
     * @return {[type]} [description]
     */
    clearWidget() {
        this.widget = null;
    }

    /**
     * 事件绑定
     * @param {any} element  绑定dom
     * @param {any} event    事件类型
     * @param {any} listener 方法
     */
    addEvent(element, event, listener, bubble = false) {
        if (element.addEventListener) {
            element.addEventListener(event, listener, bubble);
        } else if (element.attachEvent) {
            element.attachEvent('on' + event, listener);
        } else {
            element['on' + event] = listener;
        }
    }

    /**
     * 获取实例化
     * @return {[type]} [description]
     */
    getInstance(component, props = {}, data = {}, parent = null, el = null) {
        let instance = new component({
            propsData: props,
            parent: parent,
            data() {
                return data;
            },
            el: el ? el : document.createElement('div')
        })
        return instance;
    }

    /**
     * 处理数据验证
     * @return {Boolean} [description]
     */

    isRegulation(config) {
        console.log("目标", config);
        console.log("溯源", this.widget);
        if (!config || !this.widget) {
            return false;
        }
        //目标元素
        let target = {
            name: config.name,
            amount: config.regulation.amount,
            scope: config.regulation.scope,
            number: config.slot.length
        }
        //数据源
        let source = {
            name: this.widget.name,
            amount: this.widget.regulation.amount,
            scope: this.widget.regulation.scope
        }
        //判断如果为对象集则判断对象集
        if (Object.prototype.toString.call(config.slot) === '[object Object]') {
            if (target.scope[0] && target.scope[0].substring(0, 1) === '-') {
                if (target.scope.indexOf('-' + source.name) == -1) {
                    return true;
                }
            } else if (target.scope[0]) {
                if (target.scope.indexOf(source.name) != -1) {
                    return true;
                }
            }
        }
        //判断数量限制
        else {
            if (target.number < target.amount) {
                if (target.scope[0] && target.scope[0].substring(0, 1) === '-') {
                    if (target.scope.indexOf('-' + source.name) == -1) {
                        return true;
                    }
                } else if (target.scope[0]) {
                    if (target.scope.indexOf(source.name) != -1) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 获取父级
     * @return {[type]} [description]
     */
    getParent(vm, level) {
        if (level === false) {
            return vm;
        } else {
            let cache = vm;
            for (let i in level) {
                let item = level[i];
                cache = cache.$children[item]
            }
            return cache
        }
    }

    /**
     * 深度拷贝
     * @param  {[type]} obj   [description]
     * @param  {Array}  cache [description]
     * @return {[type]}       [description]
     */
    deepCopy(obj, cache = []) {
        // just return if obj is immutable value
        if (obj === null || typeof obj !== 'object') {
            return obj
        }

        // if obj is hit, it is in circular structure
        const hit = find(cache, c => c.original === obj)
        if (hit) {
            return hit.copy
        }

        const copy = Array.isArray(obj) ? [] : {}
        // put the copy into cache at first
        // because we want to refer it in recursive deepCopy
        cache.push({
            original: obj,
            copy
        })

        Object.keys(obj).forEach(key => {
            copy[key] = this.deepCopy(obj[key], cache)
        })

        return copy
    }

    showPlace(el, vnode) {
        if (this.mark.length == 0 || (vnode.context._uid != this.mark[0]._uid && this.mark.length < 2)) {
            this.closePlace()
            let instance = Core.getInstance(Vue.extend(add_mark));
            let dom = el.appendChild(instance.$el);
            this.mark.push({ _uid: vnode.context._uid, dom: dom, parent: el });
        }

    }

    closePlace() {
        if (this.mark.length > 0) {
            let model = this.mark.shift();
            model.parent.removeChild(model.dom);
        }
    }

}

export let Core = new dragdrop();

/**
 * 指令合集
 * @type {Object}
 */
export let directives = {
    /**
     * 工具拖拽
     * @type {Object}
     */
    iwidget: {
        /**
         * 指令初始化
         * @type {Object}
         */
        inserted: function(el, binding, vnode) {
            //添加拖拽属性
            el.setAttribute("draggable", true);
            //添加拖拽开始事件
            Core.addEvent(el, 'dragstart', function(el) {
                console.log("查看iwidget", binding.value);
                Core.setWidget(binding.value)
            });
            //添加拖拽结束事件
            Core.addEvent(el, 'dragend', function(el) {
                Core.closePlace();
                Core.clearWidget()
            });
        }
    },
    /**
     * 拖拽放置画布
     * @type {Object}
     */
    icanva: {
        /**
         * 指令绑定
         * @type {Object}
         */
        bind: function(el, binding, vnode) {
            //阻止默认方法
            Core.addEvent(el, 'dragover', function(event) {
                event.preventDefault();
            })
        },
        /**
         * 指令初始化
         * @type {Object}
         */
        inserted: function(el, binding, vnode) {
            // 添加拖拽事件
            Core.addEvent(el, 'drop', function(event) {

                Core.closePlace();
                if (Core.isRegulation(vnode.context.value)) {
                    console.log("验证通过")
                    let slot = el.dataset.slot ? el.dataset.slot : false;
                    Core.handleEvent(vnode.context.value, Core.widget, slot);
                } else {
                    console.log("验证不过");
                }
                //处理冒泡问题
                event.cancelBubble = true;
                event.stopPropagation();
            })
            //拖拽进入
            Core.addEvent(el, 'dragenter', function(event) {
                Core.showPlace(el, vnode)
                //处理冒泡问题
                event.cancelBubble = true;
                event.stopPropagation();
            })
        },
        update: function(el, binding, vnode) {
            // console.log("之心耿耿");
        }
    },
    /**
     * 编辑指令
     * @type {Object}
     */
    iedit: {
        /**
         * 指令初始化
         * @type {Object}
         */
        inserted: function(el, binding, vnode) {

            Core.addEvent(el, 'click', function() {

                // 隐藏资源板块右键菜单
                let children = vnode.context.$root.$children[0].$children[0].$children[0].$children;
                children[children.length - 1].isDisplay = false;

                let vm = vnode.context;
                let uid = "VM_" + vm._uid;
                let data = null;
                if (binding.value) {
                    data = binding.value;
                } else {
                    data = vm.value
                }
                let instance = Core.getInstance(Vue.extend(add_edit), {
                    value: data
                }, {}, vm);
                //处理冒泡问题
                event.cancelBubble = true;
                event.stopPropagation();
            });
        }
    },
    /**
     * 新增单元格
     * @type {Object}
     */
    icolumn: {
        /**
         * 指令初始化
         * @type {Object}
         */
        inserted: function(el, binding, vnode) {
            //在DOM结构写入添加按钮
            // let el2 = Core.handleColumn(el, binding.value, vnode.context);
            // Core.addEvent(el, 'click', function() {
            //   let widget = Core.deepCopy(widgets_column);
            //   Core.handleEvent(vnode.context.value, widget)
            // });
            // 

            let button = Core.getInstance(Vue.extend(add_column), {}, {}, vnode.context);
            el.appendChild(button.$el);
            Core.addEvent(button.$el, "click", function() {
                let widget = Core.deepCopy(widgets_column);
                Core.handleEvent(vnode.context.value, widget)
            })
        }
    },
    /**
     * 新增表单元素
     * @type {Object}
     */
    ilabel: {
        /**
         * 指令初始化
         * @type {Object}
         */
        inserted: function(el, binding, vnode) {
            //在DOM结构写入添加按钮
            let button = Core.getInstance(Vue.extend(add_label), {}, {}, vnode.context);
            el.appendChild(button.$el);
            Core.addEvent(button.$el, "click", function() {
                console.log("出书")
                let widget = Core.deepCopy(widgets_label);
                Core.handleEvent(vnode.context.value, widget)
            })
        }
    }
}